package com.xw.tools.view;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import com.xw.tools.util.MD5Utils;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextInputDialog;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.io.File;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class PasswordNotepadWin extends AbstractWin {

    private TextArea inputTextArea;

    private String filePath;

    private String password;

    private String lastPath;

    private void start() {
        Stage stage = new Stage();
        stage.setTitle("密码记事本");
        //stage.initModality(Modality.WINDOW_MODAL);
        //stage.initOwner(primaryStage);
        Scene scene = new Scene(new VBox(), 800, 495);
        initView(scene, stage);
        stage.setScene(scene);
        stage.show();
    }

    private void initView(Scene scene, Stage stage) {
        inputTextArea = new TextArea();
        inputTextArea.setFont(Font.font(16));
        MenuBar menuBar = new MenuBar();
        Menu menuFile = new Menu("文件");
        menuBar.getMenus().add(menuFile);
        MenuItem openItem = new MenuItem("打开");
        MenuItem saveItem = new MenuItem("保存");
        menuFile.getItems().add(openItem);
        menuFile.getItems().add(saveItem);
        openItem.setOnAction(event -> {
            // 打开
            FileChooser fileChooser = new FileChooser();
            FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("ct files (*.ct)",
                    "*.ct");
            fileChooser.getExtensionFilters().add(extFilter);
            if (StrUtil.isNotBlank(lastPath)) {
                fileChooser.setInitialDirectory(new File(lastPath));
            }
            File file = fileChooser.showOpenDialog(stage);
            if (file == null || !file.exists()) {
                return;
            }
            filePath = file.getAbsolutePath();
            lastPath = file.getParentFile().getAbsolutePath();
            byte[] tbs = FileUtil.readBytes(filePath);
            if (tbs.length <= 3 || !"abcdef".equalsIgnoreCase(HexUtil.encodeHexStr(new byte[] {tbs[0], tbs[1], tbs[2]}))) {
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setHeaderText("文件格式不正确!");
                alert.showAndWait();
                return;
            }

            TextInputDialog inputDialog = new TextInputDialog();
            inputDialog.setTitle("密码");
            inputDialog.setHeaderText("输入密码:");
            inputDialog.showAndWait();
            if (StrUtil.isNotBlank(inputDialog.getResult())) {
                password = inputDialog.getResult();
            } else {
                return;
            }

            byte[] key = genKey(password);
            AES aes = SecureUtil.aes(key);
            byte[] bytes = FileUtil.readBytes(filePath);
            byte[] dest = new byte[bytes.length - 3];
            ArrayUtil.copy(bytes, 3, dest, 0, dest.length);
            try {
                byte[] data = aes.decrypt(dest);
                inputTextArea.setText(new String(data, "utf-8"));
            } catch (Exception e) {
                password = "";
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setHeaderText("密码错误!");
                alert.showAndWait();
            }
        });
        saveItem.setOnAction(event -> {
            // 保存
            String text = inputTextArea.getText();
            if (StrUtil.isBlank(text)) {
                return;
            }

            if (StrUtil.isBlank(filePath)) {
                FileChooser fileChooser = new FileChooser();
                FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("ct files (*.ct)",
                        "*.ct");
                fileChooser.getExtensionFilters().add(extFilter);
                if (StrUtil.isNotBlank(lastPath)) {
                    fileChooser.setInitialDirectory(new File(lastPath));
                }
                File file = fileChooser.showSaveDialog(stage);
                if (file != null) {
                    filePath = file.getAbsolutePath();
                    lastPath = file.getParentFile().getAbsolutePath();
                }
            }

            if (StrUtil.isBlank(password)) {
                while (true) {
                    TextInputDialog inputDialog = new TextInputDialog();
                    inputDialog.setTitle("密码");
                    inputDialog.setHeaderText("输入密码:");
                    inputDialog.showAndWait();
                    if (StrUtil.isNotBlank(inputDialog.getResult())) {
                        password = inputDialog.getResult();
                        break;
                    }
                }
            }

            //gen key
            byte[] key = genKey(password);
            AES aes = SecureUtil.aes(key);
            byte[] encrypt = aes.encrypt(text);
            byte[] mark = HexUtil.decodeHex("abcdef");
            FileUtil.writeBytes(mark, filePath);
            FileUtil.writeBytes(encrypt, new File(filePath), 0, encrypt.length, true);
        });

        VBox box = (VBox) scene.getRoot();
        box.getChildren().add(menuBar);
        box.getChildren().add(inputTextArea);
        VBox.setVgrow(inputTextArea,  Priority.ALWAYS);
    }

    @Override
    public void show() {
        start();
    }

    public byte[] genKey(String password) {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            kgen.init(256, new SecureRandom((password + MD5Utils.MD5Encode(password, "utf-8")).getBytes()));
            SecretKey secretKey = kgen.generateKey();
            return secretKey.getEncoded();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }

    }
}
